package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.constants.WmNewsConstants;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.threadlocal.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmMaterialService;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsMaterialService;
import com.heima.wemedia.service.WmNewsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private WmNewsAuditService wmNewsAuditService;


    /**
     * 查询文章列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult list(WmNewsPageReqDto dto) {
        //1.非空判断
        dto.checkParam();
        //2.分页查询
        IPage<WmNews> page=new Page<>(dto.getPage(),dto.getSize());
        LambdaQueryWrapper<WmNews> queryWrapper= Wrappers.lambdaQuery();
        //2.1 根据状态查询
        if(dto.getStatus()!=null){
            queryWrapper.eq(WmNews::getStatus,dto.getStatus());
        }

        //2.2 根据关键字查询
        if(!StringUtils.isEmpty(dto.getKeyword())){
            queryWrapper.like(WmNews::getTitle,dto.getKeyword());
        }

        //2.3 根据频道id查询
        if(dto.getChannelId()!=null){
            queryWrapper.eq(WmNews::getChannelId,dto.getChannelId());
        }

        //2.4 根据开始和结束时间查询
        if(dto.getBeginPubdate()!=null && dto.getEndPubdate()!=null){
            queryWrapper.between(WmNews::getPublishTime,dto.getBeginPubdate(),dto.getEndPubdate());
        }

        //2.5 根据登录用户id查询
        queryWrapper.eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId());
        queryWrapper.orderByDesc(WmNews::getCreatedTime);

        page=super.page(page,queryWrapper);

        //3.返回数据结果
        ResponseResult result=new PageResponseResult(dto.getPage(),dto.getSize(), (int) page.getTotal());
        result.setData(page.getRecords());
        return result;
    }


    @Autowired
    private WmNewsMaterialService wmNewsMaterialService;

    @Autowired
    private WmMaterialService wmMaterialService;
    /**
     * 保存-修改-提交草稿为一体的方法
     *  主方法
     * @param dto
     * @return
     */
    @Override
    public ResponseResult submit(WmNewsDto dto) {
        //1.判断参数的合法性
        if(StringUtils.isBlank(dto.getTitle()) || StringUtils.isBlank(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.新增或修改文章（公共逻辑）
        //2.1 拷贝dto给pojo
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto, wmNews);
        //2.2 特殊处理封面图片地址images的值
        List<String> coverImageList = dto.getImages();
        if(coverImageList!=null && coverImageList.size()>0){
            //将封面图片地址列表中的所有地址取出来，拼接在一起，用逗号拼接
            String images = coverImageList.stream().collect(Collectors.joining(","));
            // String images = StringUtils.join(coverImageList, ",");
            // String images = String.join(",", coverImageList);
            wmNews.setImages(images);
        }
        //2.3 判断如果是自动布局，设置布局方式临时为空（后续逻辑，会确定最终布局方式）
        if(dto.getType()== WmNewsConstants.LAYOUT_AUTO){
            wmNews.setType(null);
        }
        //2.4 根据ID判断新增或修改文章
        ResponseResult responseResult = this.saveOrUpdateWmNews(wmNews);
        if(responseResult!=null){
            return responseResult;
        }
        //获取内容图片的地址列表
        List<String> contentImageList = extractContentImageList(dto);

        //3.保存内容图片与文章的关系
        if(dto.getStatus()==1 && contentImageList.size()>0){
            responseResult = this.saveRelation(contentImageList, WmNewsConstants.REFRENCE_CONTENT, wmNews.getId());
            if(responseResult!=null){
                return responseResult;
            }
        }

        //4. 保存封面图片与文章的关系（提交审核审核才执行）
        if(dto.getStatus()==1){
            responseResult = saveRelationForCover(dto, wmNews, contentImageList);
            if (responseResult != null) {
                return responseResult;
            }
            //5. 调用文章自动审核逻辑
            wmNewsAuditService.auditWmNews(wmNews, contentImageList);
        }
        return ResponseResult.okResult("发布文章完成");
    }
    private ResponseResult saveRelationForCover(WmNewsDto dto, WmNews wmNews, List<String> contentImageList) {
        //4.1 获取封面图片地址列表
        List<String> coverImages =  dto.getImages();

        //4.2 判断如果是自动布局，则根据自动匹配规则从内容图片里决定封面布局方式和图片多少
        if(dto.getType()==WmNewsConstants.LAYOUT_AUTO){
            int size = contentImageList.size();

            //匹配规则1：内容图片数量>=3，取3张当做封面图片，封面布局方式最终为多图布局
            if(size>=3){
                //coverImages = contentImageList.subList(0,3);
                coverImages = contentImageList.stream().limit(3).collect(Collectors.toList());
                wmNews.setType(WmNewsConstants.LAYOUT_MANY);
            } else if(size>=1){
                //匹配规则2：内容图片数量>=1，取1张当做封面图片，封面布局方式最终为单图布局
                //coverImages = contentImageList.subList(0,1);
                coverImages = contentImageList.stream().limit(1).collect(Collectors.toList());
                wmNews.setType(WmNewsConstants.LAYOUT_SINGLE);
            } else {
                //匹配规则3：内容图片数量=0，封面布局方式最终为无图布局
                wmNews.setType(WmNewsConstants.LAYOUT_NONE);
            }

            if(coverImages.size()>0){
                String images = coverImages.stream().collect(Collectors.joining(","));
                wmNews.setImages(images);
            }

            //更新文章最终封面布局方式和封面图片
            this.updateById(wmNews);
        }

        ResponseResult responseResult = null;
        if(coverImages.size()>0){
            responseResult = this.saveRelation(coverImages, WmNewsConstants.REFRENCE_COVER, wmNews.getId());
            if(responseResult!=null){
                return responseResult;
            }
        }
        return null;
    }

    private static List<String> extractContentImageList(WmNewsDto dto) {
        List<Map> contentMapList = JSON.parseArray(dto.getContent(), Map.class);
        List<String> contentImageList = new ArrayList<>();
        if(contentMapList.size()>0){
            for (Map<String,String> contentMap : contentMapList) {
                String type = contentMap.get("type");
                if("image".equals(type)){
                    String contentImageUrl = contentMap.get("value");
                    contentImageList.add(contentImageUrl);
                }
            }
        }
        return contentImageList;
    }

    private ResponseResult saveOrUpdateWmNews(WmNews wmNews) {
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());//自媒体用户id
        wmNews.setSubmitedTime(new Date());//提交时间
        wmNews.setEnable(WmNewsConstants.ENALBE_UP); //已上架

        //2.4.1 如果ID为空，则新增文章
        if(wmNews.getId()==null){
            wmNews.setCreatedTime(new Date());//创建时间
            this.save(wmNews);
        } else {
            //2.4.2 如果ID非空，则删除关系，修改文章

            //删除关系 delete from wm_news_material where news_id=?
            wmNewsMaterialService.remove(Wrappers.<WmNewsMaterial>lambdaQuery()
                    .eq(WmNewsMaterial::getNewsId, wmNews.getId()));

            //判断文章是否存在 select count(*) from wm_news where id=?
            Integer count = this.lambdaQuery().eq(WmNews::getId, wmNews.getId()).count();
            if(count<=0){
                ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章不存在无法修改");
            }
            //修改文章
            this.updateById(wmNews);
        }
        return null;
    }

    /**
     * 保存关系
     * @param imageList  图片地址列表
     * @param type 引用类型
     * @param wmNewsId 文章id
     * @return
     */
    private ResponseResult saveRelation(List<String> imageList,Short type,Integer wmNewsId){
        //3.1 根据素材地址找到素材ID   select id from wm_material where url in (?,?,?)
        List<WmMaterial> wmMaterialList = wmMaterialService.lambdaQuery()
                .select(WmMaterial::getId)
                .in(WmMaterial::getUrl, imageList)
                .list();
        Set<Integer> materialIdList = wmMaterialList.stream().map(WmMaterial::getId).collect(Collectors.toSet());
        if(materialIdList.size()!=imageList.size()){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "素材不存在");
        }

        //3.2 保存内容图片与文章关系
        int ord = 0;
        List<WmNewsMaterial> wmNewsMaterialList = new ArrayList<>();
        for (Integer materialId : materialIdList) {
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setNewsId(wmNewsId); //文章id
            wmNewsMaterial.setMaterialId(materialId);//素材id
            wmNewsMaterial.setType(type);//内容引用
            wmNewsMaterial.setOrd((short)ord++);//序号
            wmNewsMaterialList.add(wmNewsMaterial);
        }
        //insert into wm_news_material(news_id,material_id,type,ord) values (100,1,0,0),(100,2,0,1),(100,3,0,2)
        wmNewsMaterialService.saveBatch(wmNewsMaterialList);

        return null;
    }

    /**
     * 文章上下架
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
       //TODO
        return ResponseResult.okResult("文章上下架完成");
    }
}
